package com.eastfair.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.common.dao.AuthCodeMapper;
import com.eastfair.common.dto.AuthCodeDTO;
import com.eastfair.common.entity.AuthCode;
import com.eastfair.common.entity.AuthCodeUser;
import com.eastfair.common.service.AuthCodeService;
import com.eastfair.common.service.AuthCodeUserService;
import com.eastfair.common.vo.AuthCodeVO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.venueservice.entity.CreatCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 服务商对外授权码
 * </p>
 *
 * @author dqq
 * @date 2023-02-14
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class AuthCodeServiceImpl extends SuperServiceImpl<AuthCodeMapper, AuthCode> implements AuthCodeService {

    private static final String AUTH_CODE_FIELD = "auth_code";

    private static final int AUTH_CODE_LENGTH = 8;

    @Value("${com.eastfair.projectId}")
    private Long projectId;

    @Resource
    private AuthCodeUserService authCodeUserService;

    @Resource
    private AuthCodeMapper authCodeMapper;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<AuthCode> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(AuthCode model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public R<AuthCodeVO> getVOByAuthUserId(AuthCodeDTO query) {
        log.info("getVOByAuthUserId - 授权用户ID查询授权码信息, authCodeDTO={}", query);
        ContextUtil.setProjectId(projectId);
        // 查询外部用户绑定的授权码列表
        List<AuthCodeUser> existAuthCodeUserList = authCodeUserService.listByAuthUserId(query.getAuthUserId());
        if (existAuthCodeUserList == null || existAuthCodeUserList.isEmpty()) {
            return R.result(1001, null, "用户未绑定授权码");
        }
        AuthCode authCode = null;
        for (AuthCodeUser authCodeUser: existAuthCodeUserList) {
            String authCodeString = authCodeUser.getAuthCode();
            AuthCode existAuthCode = getByAuthCode(authCodeString);
            if (existAuthCode == null) {
                continue;
            }
            // 查询到当前展会，当前服务商类型已绑定的授权码
            if (existAuthCode.getExhibitionManageId().equals(query.getExhibitionManageId())) {
                authCode = existAuthCode;
            }
        }
        // 授权码为空，则没在当前展会绑定过
        if (authCode == null) {
            return R.result(1002, null, "用户在该展会未绑定授权码");
        }
        // 授权码失效
        LocalDateTime validStartTime = authCode.getValidStartTime();
        LocalDateTime validEndTime = authCode.getValidEndTime();
        if (validStartTime == null || validEndTime == null) {
            return R.result(1003, null, "授权码已失效，需要绑定新的授权码");
        }
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(validStartTime) || now.isAfter(validEndTime)) {
            return R.result(1003, null, "授权码已失效，需要绑定新的授权码");
        }
        // 更新最后登录时间
        authCodeUserService.updateLastLoginTime(query.getAuthUserId(), authCode.getAuthCode());
        // 返回用户授权信息
        AuthCodeVO authCodeVO = BeanUtil.toBean(authCode, AuthCodeVO.class);
        return R.successDef(authCodeVO);
    }

    @Override
    public Page<AuthCodeVO> listAuthCodeVO(PageParams<AuthCodeDTO> pageParams) {
        Page<AuthCode> pageParam = pageParams.buildPage();
        AuthCodeDTO authCodeDTO = pageParams.getModel();
        log.info("listAuthCodeVO - 分页查询授权码VO, pageParams={}", pageParams);
        QueryWrapper<AuthCode> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("ac.is_deleted", BusinessConstant.DELETE_NO)
                .eq(authCodeDTO.getServiceProviderId() != null,
                        "ac.service_provider_id", authCodeDTO.getServiceProviderId())
                .eq(StrUtil.isNotBlank(authCodeDTO.getServiceProviderType()),
                        "ac.service_provider_type", authCodeDTO.getServiceProviderType())
                .eq(authCodeDTO.getExhibitionManageId() != null,
                        "ac.exhibition_manage_id", authCodeDTO.getExhibitionManageId())
                .groupBy("ac.id")
        ;
        return authCodeMapper.listAuthCodeVO(pageParam, queryWrapper);
    }

    @Override
    public AuthCodeVO getVOById(Long id) {
        log.info("getVOById - ID 查询授权码, id={}", id);
        AuthCode authCode = getById(id);
        if (authCode == null) {
            return null;
        }
        return BeanUtil.toBean(authCode, AuthCodeVO.class);
    }

    @Override
    public AuthCode getByAuthCode(String authCode) {
        log.info("getByAuthCode - 授权码查询, authCode={}", authCode);
        QueryWrapper<AuthCode> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(AuthCode::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(AuthCode::getIsEnabled, BusinessConstant.ENABLE_YES)
                .eq(StrUtil.isNotBlank(authCode), AuthCode::getAuthCode, authCode)
        ;
        List<AuthCode> list = list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public AuthCode getValidByAuthCode(String authCode) {
        log.info("getValidByAuthCode - 授权码查询有效的授权码, authCode={}", authCode);
        LocalDateTime now = LocalDateTime.now();
        QueryWrapper<AuthCode> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(AuthCode::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(AuthCode::getIsEnabled, BusinessConstant.ENABLE_YES)
                .eq(StrUtil.isNotBlank(authCode), AuthCode::getAuthCode, authCode)
                .le(AuthCode::getValidStartTime, now)
                .ge(AuthCode::getValidEndTime, now)
        ;
        List<AuthCode> list = list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAuthCode(AuthCodeDTO authCodeDTO) {
        log.info("saveAuthCode - 保存授权码, authCodeDTO={}", authCodeDTO);
        if (StrUtil.isBlank(authCodeDTO.getAuthCode())) {
            String authCodeString = CreatCode.creatCode(baseMapper, AUTH_CODE_FIELD, AUTH_CODE_LENGTH, "");
            authCodeDTO.setAuthCode(authCodeString);
        }
        AuthCode authCode = BeanUtil.toBean(authCodeDTO, AuthCode.class);
        return save(authCode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAuthCode(AuthCodeDTO authCodeDTO) {
        log.info("updateAuthCode - 更新授权码, authCodeDTO={}", authCodeDTO);
        AuthCode authCode = BeanUtil.toBean(authCodeDTO, AuthCode.class);
        return updateById(authCode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeAuthCodeByIds(List<Long> ids) {
        log.info("removeAuthCodeByIds - 移除授权码, ids={}", ids);
        List<AuthCode> authCodeList = listByIds(ids);
        if (authCodeList == null || authCodeList.isEmpty()) {
            return true;
        }
        // 移除授权码
        removeByIdsOfLogic(authCodeList);
        // 移除授权码与用户关系
        List<String> authCodeStringList = authCodeList
                .stream()
                .map(AuthCode::getAuthCode)
                .collect(Collectors.toList());
        return authCodeUserService.removeByAuthCode(authCodeStringList);
    }
}
